package com.example.blood_sugar.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.example.blood_sugar.bean.BSRecord;
import com.example.blood_sugar.db.RecordDbSchema.RecordTable;
import com.example.blood_sugar.utils.DateUtil;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 记录的持有者类，封装了一切在界面中需要操作数据库的方法
 */
public class BSRecordHolder {

    private static BSRecordHolder sBSRecordHolder;

//    private List<BSRecord> mBSRecords;

    private Context mContext;

    private SQLiteDatabase mDatabase;

    /**
     * 获取本类实例
     * @param context
     * @return
     */
    public static BSRecordHolder get(Context context){
        if (sBSRecordHolder == null){
            sBSRecordHolder = new BSRecordHolder(context);
        }
        return sBSRecordHolder;
    }

    /**
     * 私有化构造方法，借用整个应用的上下文将本类设计成单例
     * @param context
     */
    private BSRecordHolder(Context context) {
        mContext = context.getApplicationContext();
//        mBSRecords = new ArrayList<>();
        mDatabase = new RecordBaseHelper(mContext).getWritableDatabase();
    }

    /**
     * 获得所有的记录，未来数据较大时应去掉，改为 分页查询
     * @return
     */
    public List<BSRecord> getBSRecords() {
//        return mBSRecords;
        List<BSRecord> bsRecords = new ArrayList<>();
        // 获得游标cursor
        RecordCursorWrapper cursor = queryRecords(null, null);
        try {
           cursor.moveToFirst();
           while (!cursor.isAfterLast()) { // 是否after last (是否在最后一个之后)? 如果否，继续循环
               bsRecords.add(cursor.getBsRecord());
               cursor.moveToNext();
           }
        } finally {
            cursor.close();
        }
        return bsRecords;
    }

    /**
     * 获得最新n数量的记录
     * @param n
     * @return
     */
    public List<BSRecord> getBSRecords(int n) {
//        Date date = new Date();
//        date.setHours(0);
//        date.setMinutes(0);
//        date.setSeconds(0);
//        if (mBSRecords.size() == 0){
//            for (int i = 1; i <= n; i ++) {
////                mBSRecords.add(new BSRecord(new Date(date.getTime() - 24 * 60 * 60 * 1000 * (n - i))));
//                mBSRecords.add(new BSRecord(DateUtil.getPreDate(date, n- i)));
//            }
//            return mBSRecords;
//        }
//        Date temp = mBSRecords.get(mBSRecords.size() - 1).getDate();
//        if (!DateUtil.getDay(date.getTime()).equals(DateUtil.getDay(temp.getTime()))) {
//            int dayDiff = (int) DateUtil.getDayDiff(temp, date);
//            for (int i = n - dayDiff + 1; i <= n; i++) {
//                mBSRecords.add(new BSRecord(DateUtil.getPreDate(date, n- i)));
//            }
//        }
//        if (mBSRecords.size() < n) {
//            int size = mBSRecords.size();
//            for (int i = size; i <= n; i++) {
//                mBSRecords.add(0, new BSRecord(DateUtil.getPreDate(date, i)));
//            }
//        }
//        /**
//         * Returns a view of the portion of this list between the specified
//         * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If
//         * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
//         * empty.)  The returned list is backed by this list, so non-structural
//         * changes in the returned list are reflected in this list, and vice-versa.
//         * The returned list supports all of the optional list operations supported
//         * by this list.<p> (包括fromIndex，不包括toIndex)
//         */
//        return mBSRecords.subList(mBSRecords.size() - n, mBSRecords.size());
        int initNum = n;
        if (initNum < 100)
            initNum = 100;
        Date date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        int count = getRecordsCount();
        if (count == 0){
            try {
                boolean result = true;
                mDatabase.beginTransaction();
                for (int i = 1; i <= initNum; i++) {
                    ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, initNum - i)));
                    if (mDatabase.insert(RecordTable.NAME, null, contentValues) < 0) {
                        result = false;
                        break;
                    }
                }
                if (result) {
                    mDatabase.setTransactionSuccessful();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != mDatabase) {
                        mDatabase.endTransaction();
//                        mDatabase.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        Date temp = getLastBSRecord().getDate();
        if (!DateUtil.getDay(date.getTime()).equals(DateUtil.getDay(temp.getTime()))) {
            try {
                boolean result = true;
                mDatabase.beginTransaction();
                int dayDiff = (int) DateUtil.getDayDiff(temp, date);
                for (int i = initNum - dayDiff + 1; i <= initNum; i++) {
                    ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, initNum - i)));
                    if (mDatabase.insert(RecordTable.NAME, null, contentValues) < 0) {
                        result = false;
                        break;
                    }
                }
                if (result) {
                    mDatabase.setTransactionSuccessful();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != mDatabase) {
                        mDatabase.endTransaction();
//                        mDatabase.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        int afterCount = getRecordsCount();
        if (afterCount < initNum) {
            try {
                boolean result = true;
                mDatabase.beginTransaction();
                int dayDiff = (int) DateUtil.getDayDiff(temp, date);
                for (int i = afterCount; i <= initNum; i++) {
                    ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, i)));
                    if (mDatabase.insert(RecordTable.NAME, null, contentValues) < 0) {
                        result = false;
                        break;
                    }
                    if (result) {
                        mDatabase.setTransactionSuccessful();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != mDatabase) {
                        mDatabase.endTransaction();
//                        mDatabase.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        /**
         * Returns a view of the portion of this list between the specified
         * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If
         * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
         * empty.)  The returned list is backed by this list, so non-structural
         * changes in the returned list are reflected in this list, and vice-versa.
         * The returned list supports all of the optional list operations supported
         * by this list.<p> (包括fromIndex，不包括toIndex)
         */
        int s = getRecordsCount();
        return getBSRecords().subList(s - n, s);
    }

    /**
     * 通过time（data）获得记录
     * @param time
     * @return
     */
    public BSRecord getRSRecordByTime(long time) {
//        List<BSRecord> mBSRecords = getBSRecords(30);

//        for (int i = 0; i < mBSRecords.size(); i ++) {
//            BSRecord record = mBSRecords.get(i);
//            if (record.getDate().getTime() == time) {
//                return record;
//            }
//        }
//        return null;

        // 有毒有毒有毒！！！
//        RecordCursorWrapper cursor = queryRecords(RecordTable.Cloumns.DATE + "=?", new String[]{Long.toString(time)});
        RecordCursorWrapper cursor = queryRecords(RecordTable.Cloumns.DATE + "=" + Long.toString(time), null);
        cursor.moveToFirst();
        if (!cursor.isAfterLast())
            return cursor.getBsRecord();
        else
            return null;
    }

    /**
     * 更新记录到数据库
     * @param bsRecord
     */
    public void updateDate(BSRecord bsRecord) {
//        for (int i = 0; i < mBSRecords.size(); i ++) {
//            BSRecord record = mBSRecords.get(i);
//            if (record.getDate().getTime() == bsRecord.getDate().getTime()) {
//                for (int j = 1; j <= 8; j ++)
//                    record.setDataBySign(j, bsRecord.getDataBySign(j));
//                record.setSystolicBP(bsRecord.getSystolicBP());
//                record.setDiastolicBP(bsRecord.getDiastolicBP());
//                record.setSaccharificationValue(bsRecord.getSaccharificationValue());
//            }
//        }
        ContentValues contentValues = getContentValues(bsRecord);
//        mDatabase.update(RecordTable.NAME, contentValues,
//                RecordTable.Cloumns.DATE + "=?",
//                new String[]{bsRecord.getDate().getTime() + ""});
        mDatabase.update(RecordTable.NAME, contentValues,
                RecordTable.Cloumns.DATE + "=" + Long.toString(bsRecord.getDate().getTime()),
                null);
    }

//    public BSRecord getLastBSRecord() {
//        return mBSRecords.get(mBSRecords.size() - 1);
//    }

    /**
     * 获得最后一条记录
     * @return
     */
    public BSRecord getLastBSRecord() {
        BSRecord bsRecord = null;
        RecordCursorWrapper cursor = queryRecords(null, null);
        try {
            cursor.moveToLast();
            bsRecord = cursor.getBsRecord();
        } finally {
            cursor.close();
        }
        return bsRecord;
    }

    /**
     * 获得当前运动记录数
     * @return
     */
    public int getRecordsCount(){
        int count = 0;
        RecordCursorWrapper cursor = queryRecords(null, null);
        count = cursor.getRecordsCount();
        cursor.close();
        return count;
    }

    /**
     * 将一条记录转换成ContentValues
     * @param bsRecord
     * @return
     */
    private static ContentValues getContentValues(BSRecord bsRecord) {
        ContentValues values = new ContentValues();
        values.put(RecordTable.Cloumns.DATE, bsRecord.getDate().getTime());
        values.put(RecordTable.Cloumns.DAWN, bsRecord.getDawn());
        values.put(RecordTable.Cloumns.BEFORE_BREAKFAST, bsRecord.getBeforeBreakfast());
        values.put(RecordTable.Cloumns.AFTER_BREAKFAST, bsRecord.getAfterBreakfast());
        values.put(RecordTable.Cloumns.BEFORE_LUNCH, bsRecord.getBeforeLunch());
        values.put(RecordTable.Cloumns.AFTER_LUNCH, bsRecord.getAfterLunch());
        values.put(RecordTable.Cloumns.BEFORE_DINNER, bsRecord.getBeforeDinner());
        values.put(RecordTable.Cloumns.AFTER_DINNER, bsRecord.getAfterDinner());
        values.put(RecordTable.Cloumns.BEFORE_SLEEP, bsRecord.getBeforeSleep());
        values.put(RecordTable.Cloumns.SYSTOLIC_BP, bsRecord.getSystolicBP());
        values.put(RecordTable.Cloumns.DIASTOLIC_BP, bsRecord.getDiastolicBP());
        values.put(RecordTable.Cloumns.SACCHARIFICATION_VALUE, bsRecord.getSaccharificationValue());
        return values;
    }

    /**
     * 查询方法
     * @param whereClause
     * @param whereArgs
     * @return
     */
    private RecordCursorWrapper queryRecords(String whereClause, String[] whereArgs) {
        Cursor cursor = mDatabase.query(
                RecordTable.NAME,
                null,
                whereClause,
                whereArgs,
                null,
                null,
                RecordTable.Cloumns.DATE
        );
        return new RecordCursorWrapper(cursor);
    }
}
